<template>
  <div class="role_box" v-loading="loading">
    <div class="role_addbtn">
      <el-button icon="plus" @click="openAddDialog()" type="primary">
        新增角色
      </el-button>
    </div>
    <el-table
      :data="RoleDatas?.list"
      row-key="id"
      border
      :header-row-style="{ color: '#232324', fontWeight: 'bold' }"
    >
      <el-table-column align="center" label="ID" min-width="50" prop="id" />
      <el-table-column
        align="center"
        label="名称"
        min-width="120"
        prop="name"
      />
      <el-table-column
        align="center"
        label="编码"
        min-width="200"
        prop="code"
      />
      <el-table-column align="center" label="状态" min-width="75">
        <template #default="scope">
          <el-tag v-if="scope.row.status == 1" type="success">正常</el-tag>
          <el-tag v-else type="danger">停用</el-tag>
        </template>
      </el-table-column>
      <el-table-column
        align="center"
        label="排序"
        min-width="200"
        prop="sort"
      />
      <el-table-column
        align="center"
        label="创建时间"
        min-width="180"
        prop="createTime"
      />
      <el-table-column
        align="center"
        label="更新时间"
        min-width="180"
        prop="updateTime"
      />
      <el-table-column align="center" fixed="right" label="操作" width="300">
        <template #default="scope">
          <el-button
            type="primary"
            link
            icon="edit"
            @click="openEditDialog(scope.row)"
          >
            编辑
          </el-button>
          <el-popconfirm
            :icon="InfoFilled"
            icon-color="#626AEF"
            width="180"
            title="是否删除该角色?"
            @confirm="deleteRoleById(scope.row.id)"
          >
            <template #reference>
              <el-button type="primary" link icon="delete">删除</el-button>
            </template>
          </el-popconfirm>
          <el-button
            type="primary"
            link
            icon="setting"
            @click="openDrawer(scope.row.id)"
          >
            设置权限
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
      style="margin-top: 12px"
      v-model:current-page="rolePageParmas.pageNum"
      v-model:page-size="rolePageParmas.pageSize"
      :page-sizes="[10, 20, 40]"
      :background="true"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />

    <el-dialog
      v-model="dialogFormVisible"
      :title="dialogTitle"
      style="min-width: 400px"
    >
      <el-form
        v-if="dialogFormVisible"
        ref="roleForms"
        :inline="true"
        :model="roleForm"
        :rules="rules"
        label-position="top"
        label-width="85px"
      >
        <el-form-item label="角色名name" prop="name" style="width: 60%">
          <el-input v-model="roleForm.name" placeholder="请输入角色名" />
        </el-form-item>
        <el-form-item label="编码code" prop="code" style="width: 60%">
          <el-input v-model="roleForm.code" placeholder="请输入角色的编码" />
        </el-form-item>
        <el-form-item
          label="排序sort"
          :min="1"
          :max="100"
          prop="sort"
          style="width: 60%"
        >
          <el-input-number v-model="roleForm.sort" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogFormVisible = false">取消</el-button>
          <el-button type="primary" @click="formConfirm(roleForms)">
            提交
          </el-button>
        </span>
      </template>
    </el-dialog>

    <el-drawer v-model="drawerVisible" custom-class="auth-drawer" size="40%">
      <template #header>
        <h1 style="font-weight: bold">角色菜单权限</h1>
      </template>
      <template #default style="padding: 0px">
        <div class="drawer-container">
          <div class="drawer-header">
            <el-input
              v-model="filterText"
              placeholder="筛选"
              style="width: 60%"
            />
            <el-button type="primary" @click="treeConfirm()">确 定</el-button>
          </div>
          <div style="margin-top: 16px">
            <el-tree
              ref="treeRef"
              :data="menuOptions"
              show-checkbox
              default-expand-all
              node-key="id"
              highlight-current
              :props="defaultProps"
              :filter-node-method="filterNode"
              style="font-size: 16px"
            />
          </div>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, reactive, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { InfoFilled } from '@element-plus/icons-vue'
import type { ElTree, FormInstance } from 'element-plus'
import {
  reqAddRole,
  reqAddRoleMenu,
  reqDeleteRole,
  reqRoleInfoPage,
  reqUpdateRole,
} from '@/api/role'
import {
  RoleInfoPageParams,
  RoleInfoRes,
  RoleMenusParams,
  RolePageRes,
  RoleParams,
} from '@/api/role/type'
import { reqGetMenuOption, reqGetMenuOptionsById } from '@/api/menu'
import { MenuInfoRes } from '@/api/menu/type'

interface Tree {
  [key: string]: any
}
const treeRef = ref<InstanceType<typeof ElTree>>()

const defaultProps = {
  children: 'children',
  label: 'label',
}

onMounted(async () => {
  await getRoleInfoPage()
  await getMenuOptions()
})

const dialogFormVisible = ref<boolean>(false)
const drawerVisible = ref<boolean>(false)
const filterText = ref<string>()
const rolePageParmas: RoleInfoPageParams = reactive({
  pageNum: 1,
  pageSize: 10,
})
const RoleDatas = ref<RolePageRes>()
const total = ref(0)
const loading = ref(false)
const menuOptions = ref<Tree[]>()
const selectedRoleId = ref(0)
const directoryMenuIds = ref<number[]>([])

const roleForms = ref<FormInstance>()
let roleForm: RoleParams = reactive({
  id: 0,
  name: '',
  code: '',
  sort: 1,
})

const rules = reactive({
  name: [{ required: true, message: '请输入角色名', trigger: 'blur' }],
  code: [{ required: true, message: '请输入角色编码', trigger: 'blur' }],
  sort: [{ required: true, message: '请选择排列顺序', trigger: 'blur' }],
})

// 添加菜单方法，id为 0则为添加根菜单
const dialogTitle = ref('新增角色')
const isEdit = ref(false)

watch(filterText, (val) => {
  treeRef.value!.filter(val)
})

const filterNode = (value: string, data: Tree) => {
  if (!value) return true
  return data.label.includes(value)
}

const getRoleInfoPage = async () => {
  loading.value = true
  try {
    const { data } = await reqRoleInfoPage(rolePageParmas)
    RoleDatas.value = data
    total.value = data.total
  } catch (error) {
    if (error instanceof Error) {
      ElMessage.error(error.message)
    }
  } finally {
    loading.value = false
  }
}

const getMenuOptions = async () => {
  try {
    const { data } = await reqGetMenuOption()
    menuOptions.value = handleMenuOption(data)
    data.forEach((item) => {
      if (item.children.length > 0) {
        directoryMenuIds.value?.push(item.id)
      }
    })
  } catch (error) {
    if (error instanceof Error) {
      ElMessage.error(error.message)
    }
  }
}

const deleteRoleById = async (id: number) => {
  try {
    const { message } = await reqDeleteRole(id)
    ElMessage.success(message)
  } catch (error) {
    ElMessage.error((error as Error).message)
  }
}

const addRole = async () => {
  try {
    const { message } = await reqAddRole(roleForm)
    ElMessage.success(message)
    roleForm = {
      id: 0,
      name: '',
      code: '',
      sort: 1,
    }
    await getRoleInfoPage()
  } catch (error) {
    ElMessage.error((error as Error).message)
  }
}

const updateRole = async () => {
  try {
    const { message } = await reqUpdateRole(roleForm)
    ElMessage.success(message)
    await getRoleInfoPage()
  } catch (error) {
    ElMessage.error((error as Error).message)
  }
}

const formConfirm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid) => {
    if (valid) {
      if (isEdit.value) {
        updateRole()
      } else {
        addRole()
      }
      dialogFormVisible.value = false
    }
  })
}

const openAddDialog = () => {
  isEdit.value = false
  if (roleForm.id !== 0) {
    roleForm = {
      id: 0,
      name: '',
      code: '',
      sort: 1,
    }
  }
  dialogTitle.value = '新增角色'
  dialogFormVisible.value = true
}
// 修改菜单方法
const openEditDialog = async (data: RoleInfoRes) => {
  isEdit.value = true
  dialogTitle.value = '编辑角色'
  roleForm.id = data.id
  roleForm.name = data.name
  roleForm.code = data.code
  roleForm.sort = data.sort
  dialogFormVisible.value = true
}

const handleSizeChange = (val: number) => {
  getRoleInfoPage()
}
const handleCurrentChange = (val: number) => {
  getRoleInfoPage()
}

const openDrawer = (roleId: number) => {
  getMenuOptionsById(roleId)
  drawerVisible.value = true
  selectedRoleId.value = roleId
}

const getMenuOptionsById = async (roleId: number) => {
  try {
    const { data } = await reqGetMenuOptionsById(roleId)
    const result = data.filter(
      (itemA) => !directoryMenuIds.value.some((itemB) => itemA === itemB),
    )
    treeRef.value!.setCheckedKeys(result, false)
  } catch (error) {
    ElMessage.error((error as Error).message)
  }
}

const handleMenuOption = (data: MenuInfoRes[]) => {
  let optionResult: Tree[] = []
  data.forEach((item) => {
    let one: Tree = {
      id: item.id,
      label: item.title,
      children: [],
    }
    optionResult.push(one)
    if (item.children.length > 0) {
      one.children = handleMenuOption(item.children)
    }
  })
  return optionResult
}

const treeConfirm = async () => {
  let roleMenus: RoleMenusParams = {
    roleId: selectedRoleId.value,
    menuIds: treeRef.value!.getCheckedKeys(false) as number[],
  }
  let fatherMenus = treeRef.value!.getHalfCheckedKeys() as number[]
  roleMenus.menuIds.push(...fatherMenus)
  try {
    const { message } = await reqAddRoleMenu(roleMenus)
    ElMessage.success(message)
    drawerVisible.value = false
  } catch (error) {
    ElMessage.error((error as Error).message)
  }
}
</script>
<style scoped lang="scss">
.role_box {
  padding: 24px;

  .role_addbtn {
    margin-bottom: 12px;
    display: flex;
  }

  .icon-column {
    display: flex;
    align-items: center;

    .el-icon {
      margin-right: 8px;
    }
  }
}

.avatar-uploader .avatar {
  width: 128px;
  height: 128px;
  display: block;
}

.drawer-container {
  padding: 0px 20px;

  .drawer-header {
    display: flex;
    justify-content: space-between;
  }
}
</style>

<style lang="scss">
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 128px;
  height: 128px;
  text-align: center;
}

.el-drawer__body {
  padding: 0px;
}
</style>
